package afcp.alumni.action.event;

import java.util.LinkedList;
import java.util.List;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.Message;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import afcp.alumni.action.base.EventAction;
import afcp.alumni.action.page.AdminAction;
import afcp.alumni.file.AlumniFile;
import afcp.alumni.file.CsvFile;
import afcp.alumni.file.ExcelFile;
import afcp.alumni.file.UploadServiceBlobstore;
import afcp.alumni.service.FileUploadService;
import afcp.alumni.service.MemberService;
import afcp.alumni.service.UploadService;

@UrlBinding(UploadMemberFileAction.URL)
public class UploadMemberFileAction extends EventAction {
	
	public static final String URL = "/upload";

	private static final Log logger = LogFactory.getLog(UploadMemberFileAction.class);
	

	@SpringBean
	private UploadService uploadService;
	// = SF.upload(URL)
	@SpringBean
	private MemberService memberService;
	@SpringBean("ExcelFileUploadService")
//	@SpringBean("SimpleExcelMemberFileUploadService")
	private FileUploadService excelFileUploadService;
	@SpringBean("CsvFileUploadService")
	private FileUploadService csvFileUploadService;

	@Override
	public String getUrl() {
		return URL;
	}

	@Override
	protected String fromUrl() {
		return AdminAction.URL;
	}

	@Override
	@DefaultHandler
	public Resolution view() {
		return new RedirectResolution(AdminAction.URL);
	}

//	public String getUploadUrl() {
//		return uploadService.getUploadUrl(URL);
//	}
	
//	@ValidateNestedProperties(
//			@Validate(field="headers", required=true, on="uploadcsv")
//	)
	private CsvFile csvFile;
	
	public CsvFile getCsvFile() {
		return csvFile;
	}

	public void setCsvFile(CsvFile csvFile) {
		this.csvFile = csvFile;
	}

	public Resolution uploadcsv() {
//		return upload(csvFile);
		return upload(csvFile, csvFileUploadService);
	}

	@ValidationMethod(on = "uploadcsv")
	public void validateCsvFile(ValidationErrors errors) {
		validateFile(csvFile, errors);
	}
	
	private void validateFile(AlumniFile file, ValidationErrors errors) {

		if (file == null || file.getHeaders() == null || file.getHeaders().size() == 0) {
			
			List<Message> failed = new LinkedList<>();
			failed.add(msgObj(UploadServiceBlobstore.UPLOAD_INCORRECTHEADER));
			addFlashScope(failed);
			
			errors.addGlobalError(new LocalizableError("validation.required.valueNotPresent", "csvFile.headers"));
			
			uploadService.deleteUploadedFiles(this.context);
		}
	}
	

	// TODO chercher dans EventAction un moyen de faire une redirection vers la
	// page admin si une erreur survient à l'upload en affichant les erreurs.
//	@ValidateNestedProperties(
//			@Validate(field="headers", required=true, on="uploadexcel")
//	)
	private ExcelFile excelFile;

	public ExcelFile getExcelFile() {
		return excelFile;
	}

	public void setExcelFile(ExcelFile excelFile) {
		this.excelFile = excelFile;
	}

	public Resolution uploadexcel() {
//		return upload(excelFile);
		return upload(excelFile, excelFileUploadService);
	}

	@ValidationMethod(on = "uploadexcel")
	public void validateExcelFile(ValidationErrors errors) {
		validateFile(excelFile, errors);
	}

	// TODO ajouter un suivi de l'avancement de l'upload. Utiliser les variables
	// de session pour noter l'avancement et faire des requêtes Ajax pour le
	// rendu HTML
	private Resolution upload(AlumniFile file, FileUploadService fileUploadService) {
		// Trim is included in Stripes validation:
//		file.trimHeaders();
		// First, persist column configuration in database
		
//		List<FileColumn> oldColumns = memberService.getAllFileColumns();
//		List<FileColumn> columnsToUpdate = new LinkedList<>();
//		Map<String, String> headers = file.getHeaders();
//		for (FileColumn column : oldColumns) {
//			String newName = headers.get(column.getId());
//			if (newName != null && !newName.equals(column.getFileColumnName())) {
//				column.setFileColumnName(newName);
//				columnsToUpdate.add(column);
//			}
//		}
//		memberService.updateColumns(columnsToUpdate);
		memberService.updateColumns(file.getHeaders());
		
		logger.info("Action: upload successful. try to read uploaded file.");
		List<Message> failed = null;
		try {
			failed = uploadService.readUpload(this.context, file, fileUploadService);
		} catch (Exception e) {
			logger.error("Error while reading upload.", e);
			if (failed == null) {
				failed = new LinkedList<>();
			}
			failed.add(msgObj(UploadServiceBlobstore.UPLOAD_PROBLEM));
		}
		
		if (failed != null && !failed.isEmpty()) {
			for (Message m : failed) {
				logger.info(msgToStr(m));
			}
			addFlashScope(failed);
		} else {
			logger.info("No warning/error during upload.");
		}
		
		return fromRedirect();
	}
	
	public Resolution resetColumns() {
		memberService.resetColumns();
		return fromRedirect();
	}

}
